package com.avetti.commerce.store.adddatainput.domainmodel;

import java.io.Serializable;

import com.avetti.simplemerce.domainmodel.OrderItem;

/**
 * {@link OrderItemDataInput} domain model. Main entity of additional data input
 * subsystem.
 * @author A.Bikovskiy
 * @version 1.0 Oct 8, 2008
 */
public class OrderItemDataInput implements Serializable {
	
	private static final long serialVersionUID = 1L;

	/**
	 * Type of {@link OrderItemDataInput#getValue()}
	 * <ul>
	 * 	<li>{@link String}, length <= 255</li>
	 *  <li>{@link String}, length > 255</li>
	 *  <li>{@link Integer}</li>
	 *  <li>{@link Double}</li>
	 *  <li>{@link Boolean}</li>
	 *  <li>{@link java.util.Date}</li>
	 * </ul>
	 * @author A.Bikovskiy
	 * @version 1.0 Jan 20, 2009
	 */
	public static enum Type {
		
		String("string"),
		Text("text"),
		Integer("integer"),
		Double("double"),
		Boolean("boolean"),
		Date("date");
		
		private final String type;
		
    	private Type(String type) {
    		this.type=type;
    	}
    	
    	public String value() {
    		return type;
    	}
	}
	/** Id field*/
	private Long id;
	/** Name of parameter.*/
	private String name;
	/** Some value of parameter. Can be some of this types {@link Type}*/
	private String value;
	/** Type of value. See values of {@link Type} */
	private String type;
	/** Related {@link OrderItem} */
	private OrderItem orderItem;
	
	public OrderItemDataInput() {
		this(null, null, null, null, null);
	}

	public OrderItemDataInput(Long id) {
		this(id, null, null, null, null);
	}
	
	public OrderItemDataInput(Long id, String name, OrderItem orderItem,
			String type, String value) {
		super();
		checkType(type);
		this.id = id;
		this.name = name;
		this.orderItem = orderItem;
		this.type = type;
		this.value = value;
	}

	public OrderItemDataInput(OrderItemDataInput other) {
		this.id = other.id;
		this.name = other.name;
		this.value = other.value;
		this.type = other.type;
		this.orderItem = other.orderItem;
	}

	/**
	 * @return the id
	 */
	public Long getId() {
		return id;
	}

	/**
	 * @param id the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the value
	 */
	public String getValue() {
		return value;
	}

	/**
	 * @param value the value to set
	 */
	public void setValue(String value) {
		this.value = value;
	}

	/**
	 * @return the type
	 */
	public String getType() {
		return type;
	}

	/**
	 * @param type the type to set
	 */
	public void setType(String type) {
		checkType(type);
		this.type = type;
	}

	/**
	 * @return the orderItem
	 */
	public OrderItem getOrderItem() {
		return orderItem;
	}

	/**
	 * @param orderItem the orderItem to set
	 */
	public void setOrderItem(OrderItem orderItem) {
		this.orderItem = orderItem;
	}
	
	/**
	 * @return the type
	 */
	public Type getObjType() {
		if(this.type == null) return null;
		for (Type type : Type.values()) {
			if(type.value().equals(this.type)) {
				return type;
			}
		}
		return null;
	}

	/**
	 * @param type the type to set
	 */
	public void setType(Type type) {
		this.type = type.value();
	}
	
	/**
	 * Try convert byte[] to specific type
	 * @return the typedValue
	 */
	public Object getTypedValue() throws Exception {
		return convertValue();
	}
	
	private Object convertValue() throws Exception {
		if(this.value == null) return null;
		
		Object result = null;
		
		if(Type.Text.equals(getObjType()) || Type.String.equals(getObjType())) {
			result = this.value;
		} else if (Type.Integer.equals(getObjType())) {
			result = Integer.parseInt(this.value);
		} else if (Type.Double.equals(getObjType())) {
			result = Double.parseDouble(this.value);
		} else if (Type.Boolean.equals(getObjType())) {
			result = Boolean.parseBoolean(this.value);
		} else if (Type.Date.equals(getObjType())) {
			//result = DateUtil.parseDate(this.value, DateUtil.DATETIME_FORMATE);
		}
		
		return result;
	}

	private void checkType(String typeStr) {
		if(typeStr == null) return;
		boolean result = false;
		for (Type type : Type.values()) {
			if(type.value().equals(typeStr)) {
				result = true;
				break;
			}
		}
		if(!result) throw new IllegalArgumentException("Type: " + typeStr +
				" is undefined. Only available types is: " + Type.values());
	}
	
	@Override
	public String toString() {
		return "[" + id + "@:"
			+ " name: " + name
			+ " value: " + value
			+ " type: " + type
			+ (orderItem == null? "": (" orderItem: " + orderItem.getOrderitemid()))
			+ "]";
	}
}
